# app.py - Backend API server
from flask import Flask, jsonify, request
from flask_cors import CORS
import qlib_lin as qlib 
from qlib_lin.data import D
import pandas as pd
import json

app = Flask(__name__)
CORS(app)  # Enable CORS for frontend requests

# Initialize qlib
provider_uri = "C:/Users/Administrator/Desktop/qlib_data_cn_1d_latest"
qlib.init(provider_uri=provider_uri)

@app.route('/api/qlib-data/features', methods=['POST'])
def get_features():
    try:
        data = request.json
        instruments = data.get('instruments')
        fields = data.get('fields')
        start_time = data.get('start_time')
        end_time = data.get('end_time')
        
        # Retrieve data using qlib
        df = D.features(instruments, fields, start_time=start_time, end_time=end_time)
        
        # Convert to JSON with proper formatting
        result = {
            'data': df.reset_index().to_dict(orient='records'),
            'columns': df.reset_index().columns.tolist()
        }
        
        return jsonify(result)
    except Exception as e:
        return jsonify({'error': str(e)}), 500

@app.route('/api/qlib-data/instruments', methods=['GET'])
def get_instruments():
    try:
        market = request.args.get('market', 'csi300')
        start_time = request.args.get('start_time', '2020-01-01')
        end_time = request.args.get('end_time', '2023-12-31')
        
        # Get instrument list
        instruments = D.list_instruments(
            D.instruments(market), 
            start_time=start_time, 
            end_time=end_time
        )
        
        # Convert to a more usable format
        instruments_list = []
        for code, name in instruments.items():
            instruments_list.append({
                'code': code,
                'name': name
            })
        
        return jsonify(instruments_list)
    except Exception as e:
        return jsonify({'error': str(e)}), 500

@app.route('/api/qlib-data/calendar', methods=['GET'])
def get_calendar():
    try:
        start_time = request.args.get('start_time', '2020-01-01')
        end_time = request.args.get('end_time', '2023-12-31')
        freq = request.args.get('freq', 'day')
        
        # Get calendar
        calendar = D.calendar(start_time=start_time, end_time=end_time, freq=freq)
        
        # Convert dates to string format
        calendar_strings = [date.strftime('%Y-%m-%d') for date in calendar]
        
        return jsonify(calendar_strings)
    except Exception as e:
        return jsonify({'error': str(e)}), 500

@app.route('/api/qlib-data/latest-data', methods=['GET'])
def get_latest_data():
    try:
        market = request.args.get('market', 'csi300')
        limit = int(request.args.get('limit', 20))
        
        # Get instrument list
        instruments = D.list_instruments(
            D.instruments(market), 
            start_time='2020-01-01', 
            end_time='2023-12-31'
        )
        
        # Get latest data for instruments
        instrument_codes = list(instruments.keys())[:limit]
        fields = ['$close', '$open', '$high', '$low', '$volume']
        
        # Get latest date
        latest_date = D.calendar(start_time='2023-01-01', end_time='2023-12-31')[-1]
        previous_date = D.calendar(start_time='2023-01-01', end_time=latest_date.strftime('%Y-%m-%d'))[-2]
        
        # Get data for latest date
        latest_data = D.features(
            instrument_codes,
            fields,
            start_time=latest_date.strftime('%Y-%m-%d'),
            end_time=latest_date.strftime('%Y-%m-%d')
        )
        
        # Get data for previous date
        previous_data = D.features(
            instrument_codes,
            ['$close'],
            start_time=previous_date.strftime('%Y-%m-%d'),
            end_time=previous_date.strftime('%Y-%m-%d')
        )
        
        # Process data
        stocks = []
        for code in instrument_codes:
            latest_row = latest_data.loc[code] if code in latest_data.index else None
            previous_row = previous_data.loc[code] if code in previous_data.index else None
            
            if latest_row is not None and not latest_row.empty:
                latest_close = latest_row['$close']
                previous_close = previous_row['$close'] if previous_row is not None and not previous_row.empty else latest_close
                
                change = ((latest_close - previous_close) / previous_close * 100) if previous_close != 0 else 0
                
                stocks.append({
                    'code': code,
                    'name': instruments[code],
                    'price': latest_close,
                    'change': change,
                    'open': latest_row['$open'],
                    'high': latest_row['$high'],
                    'low': latest_row['$low'],
                    'volume': latest_row['$volume']
                })
        
        return jsonify(stocks)
    except Exception as e:
        return jsonify({'error': str(e)}), 500

# Custom stock fields endpoint
@app.route('/api/custom-fields', methods=['POST'])
def custom_stock_fields():
    try:
        data = request.json
        instruments = data.get('instruments', [])
        custom_fields = data.get('custom_fields', [])
        start_time = data.get('start_time')
        end_time = data.get('end_time')
        
        # Process custom fields logic here
        # This is a placeholder implementation
        result = {
            'status': 'success',
            'message': 'Custom fields data retrieved',
            'data': []
        }
        
        return jsonify(result)
    except Exception as e:
        return jsonify({'error': str(e)}), 500

# Strategy edit submission endpoint
@app.route('/api/strategy/edit', methods=['POST'])
def strategy_edit_submit():
    try:
        data = request.json
        strategy_id = data.get('strategy_id')
        strategy_data = data.get('strategy_data')
        
        # Process strategy edit logic here
        # This is a placeholder implementation
        result = {
            'status': 'success',
            'message': f'Strategy {strategy_id} updated successfully',
            'data': strategy_data
        }
        
        return jsonify(result)
    except Exception as e:
        return jsonify({'error': str(e)}), 500

# Strategy execution endpoint
@app.route('/api/strategy/execute', methods=['POST'])
def strategy_execute():
    try:
        data = request.json
        strategy_id = data.get('strategy_id')
        parameters = data.get('parameters', {})
        
        # Process strategy execution logic here
        # This is a placeholder implementation
        result = {
            'status': 'success',
            'message': f'Strategy {strategy_id} executed successfully',
            'execution_id': 'exec_12345',
            'results': {
                'trades': [],
                'performance': {}
            }
        }
        
        return jsonify(result)
    except Exception as e:
        return jsonify({'error': str(e)}), 500

# Strategy performance query endpoint
@app.route('/api/strategy/performance', methods=['POST'])
def strategy_performance():
    try:
        data = request.json
        strategy_id = data.get('strategy_id')
        start_time = data.get('start_time')
        end_time = data.get('end_time')
        
        # Process strategy performance query logic here
        # This is a placeholder implementation
        result = {
            'status': 'success',
            'strategy_id': strategy_id,
            'performance_data': [
                {'date': '2023-01-01', 'value': 1.5},
                {'date': '2023-01-02', 'value': 2.1},
                {'date': '2023-01-03', 'value': 1.8}
            ]
        }
        
        return jsonify(result)
    except Exception as e:
        return jsonify({'error': str(e)}), 500

# Strategy details query endpoint
@app.route('/api/strategy/details', methods=['POST'])
def strategy_details():
    try:
        data = request.json
        strategy_id = data.get('strategy_id')
        
        # Process strategy details query logic here
        # This is a placeholder implementation
        result = {
            'status': 'success',
            'strategy_id': strategy_id,
            'details': {
                'name': 'Sample Strategy',
                'type': 'custom',
                'created_at': '2023-01-01',
                'last_executed': '2023-01-03',
                'parameters': {},
                'performance': {
                    'total_return': 5.2,
                    'annual_return': 12.4,
                    'sharpe_ratio': 1.2
                }
            }
        }
        
        return jsonify(result)
    except Exception as e:
        return jsonify({'error': str(e)}), 500

# Trading request submission endpoint
@app.route('/api/trading/submit', methods=['POST'])
def trading_request_submit():
    try:
        data = request.json
        stock_code = data.get('stock_code')
        trade_type = data.get('trade_type')  # 'buy' or 'sell'
        price = data.get('price')
        quantity = data.get('quantity')
        account_id = data.get('account_id')
        
        # Process trading request logic here
        # This is a placeholder implementation
        result = {
            'status': 'success',
            'message': f'{trade_type.upper()} order for {quantity} shares of {stock_code} submitted',
            'order_id': 'order_12345',
            'execution_details': {
                'filled_quantity': quantity,
                'average_price': price,
                'commission': 0.0
            }
        }
        
        return jsonify(result)
    except Exception as e:
        return jsonify({'error': str(e)}), 500

# Portfolio data query endpoint
@app.route('/api/portfolio/data', methods=['POST'])
def portfolio_data():
    try:
        data = request.json
        account_id = data.get('account_id')
        
        # Process portfolio data query logic here
        # This is a placeholder implementation
        result = {
            'status': 'success',
            'account_id': account_id,
            'portfolio_value': 1000000.00,
            'available_balance': 250000.00,
            'positions': [
                {
                    'stock_code': '600000',
                    'stock_name': '浦发银行',
                    'quantity': 1000,
                    'cost_price': 10.00,
                    'current_price': 10.25,
                    'market_value': 10250.00,
                    'profit_loss': 250.00
                },
                {
                    'stock_code': '000001',
                    'stock_name': '平安银行',
                    'quantity': 500,
                    'cost_price': 15.00,
                    'current_price': 15.30,
                    'market_value': 7650.00,
                    'profit_loss': 150.00
                }
            ]
        }
        
        return jsonify(result)
    except Exception as e:
        return jsonify({'error': str(e)}), 500

if __name__ == '__main__':
    app.run(debug=True, port=5000)